package com.sat.client.utils

import android.content.Context
import android.util.Log
import okhttp3.*
import okio.ByteString
import java.util.concurrent.TimeUnit

class WebSocketManager(
    private val context: Context,
    private val url: String,
    private val onOpen: (() -> Unit)? = null,
    private val onMessage: ((String) -> Unit)? = null,
    private val onMessageBytes: ((ByteString) -> Unit)? = null,
    private val onClosing: ((Int, String) -> Unit)? = null,
    private val onClosed: ((Int, String) -> Unit)? = null,
    private val onFailure: ((Throwable, Response?) -> Unit)? = null
) {

    private lateinit var webSocket: WebSocket
    private val client: OkHttpClient = OkHttpClient.Builder()
        .readTimeout(0, TimeUnit.MILLISECONDS)
        .build()

    fun connect() {
        val request = Request.Builder()
            .url(url)
            .build()
        val listener = WebSocketListenerImpl()
        webSocket = client.newWebSocket(request, listener)
    }

    fun disconnect() {
        webSocket.close(1000, "Client disconnected")
    }

    fun sendMessage(message: String) {
        webSocket.send(message)
    }

    fun sendBinary(bytes: ByteArray) {
        webSocket.send(ByteString.of(*bytes))
    }

    private inner class WebSocketListenerImpl : WebSocketListener() {
        override fun onOpen(webSocket: WebSocket, response: Response) {
            Log.e("WS","WebSocket connection opened")
            onOpen?.invoke()
            sendMessage("startScreen")
        }

        override fun onMessage(webSocket: WebSocket, text: String) {
            Log.e("WS","Received message: $text")
            onMessage?.invoke(text)
        }

        override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
            onMessageBytes?.invoke(bytes)
        }

        override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
            Log.e("WS","WebSocket connection closing: $code / $reason")
            onClosing?.invoke(code, reason)
        }

        override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
            Log.e("WS","WebSocket connection closed: $code / $reason")
            onClosed?.invoke(code, reason)
        }

        override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
            Log.e("WS","WebSocket connection failed: ${t.message}")
            onFailure?.invoke(t, response)
        }
    }
}
